//
//  LogRegisterDelegate.m
//  TcpTest_Server
//
//  Created by arvintan on 12-7-28.
//  Copyright (c) 2012年 tencent. All rights reserved.
//

#import "LogInPacketCenter.h"
#import "EncryptorWithKey.h"
#import "SockPacket.h"
#import "MacroComd.h"
#import "MiniSocket.h"
#import "MainSocketDelegate.h"
#import "MysqlDB.h"

NSString *LOG_KEY = @"password";

@implementation LogInPacketCenter

-(NSData*) dataCmd:(NSData *)data cmd:(NSUInteger)cmdFlag subcmd:(NSUInteger)subCmdFlag
{
    NSUInteger length = data.length + 16;
    NSLog(@"data length is %lu,%lu",data.length,sizeof(NSUInteger));
    NSMutableData *dataWithCmd = [NSMutableData dataWithBytes:&(length) length:sizeof(NSUInteger)];
    [dataWithCmd appendBytes:&(cmdFlag) length:sizeof(NSUInteger)];
    [dataWithCmd appendBytes:&(subCmdFlag) length:sizeof(NSUInteger)];
    [dataWithCmd appendData:data];
    
    return dataWithCmd;
}


-(void)MessageDispatch: (SockPacket *)packet
{
    void *bytes = (void*)[packet.packetContent bytes];
//    NSUInteger contentLen = packet.packetLen - 2*sizeof(NSUInteger);
//    NSData     *content = [[NSData alloc] initWithBytes:(bytes+2*sizeof(NSUInteger)) length:contentLen];
    

    NSUInteger subFun = *((NSUInteger *)(bytes + sizeof(NSUInteger))); 
   //[packet.packetContent getBytes:&(subFun) range:NSMakeRange(sizeof(NSUInteger),sizeof(NSUInteger))];

    // 初始化数据库并连接
    MysqlDB *mysql = [[MysqlDB alloc] init];
    [mysql connectHost:hostIp connectUser:userName connectPassword:password connectName:dbName];
    switch (subFun) 
    {
        case CMD_LOG_LOGIN:
        {   
            //获取ID，密码长度以及密码
            NSUInteger userID = *((NSUInteger*)(bytes + 2*sizeof(NSUInteger)));
            NSUInteger pwdLen = *((NSUInteger*)(bytes + 3*sizeof(NSUInteger)));
            
            NSData *encryptPwd = [[NSData alloc] initWithBytes:(bytes + 4*sizeof(NSUInteger)) length:pwdLen];
            NSString *pwd = [[NSString alloc] initWithData:[EncryptorWithKey decryptWIthKey:encryptPwd forKey:LOG_KEY]  encoding:NSUTF8StringEncoding];
            NSString *escapePwd = [mysql doEscapeString:pwd];
            
            //数据库操作
            NSString *sqlQuery = [NSString stringWithFormat:@"select * from tbUser where UserID = '%ld' && Password = '%@'",userID,escapePwd];
            NSMutableArray *dataResult = [mysql doDataQuery:sqlQuery];
            
            for (int i = 0 ; i < [dataResult count]; ++i) {
                NSLog(@"%@",[dataResult objectAtIndex:i]);
            }
            
            //如果数据库中存在
            if ([dataResult count]) 
            {
                NSLog(@"log delegate message--->收到--- subfun is %lu\r\n",subFun);
  
                //返回个人信息
                NSArray *temp = [dataResult objectAtIndex:0];
                NSUInteger userID = [[temp objectAtIndex:0] integerValue];
                NSString *userName = [temp objectAtIndex:1];
                NSString *headImgae = [temp objectAtIndex:3];
                NSData *nameData = [userName dataUsingEncoding:NSUTF8StringEncoding];
                NSData *imageData = [headImgae dataUsingEncoding:NSUTF8StringEncoding];
                NSUInteger nameLen = [nameData length];
                NSUInteger imageLen = [imageData length];
                NSMutableData *data = [[NSMutableData alloc] initWithBytes:&(userID) length:sizeof(NSUInteger)];
                [data appendBytes:&(nameLen) length:sizeof(NSUInteger)];
                [data appendBytes:&(imageLen) length:sizeof(NSUInteger)];
                [data appendData:nameData];
                [data appendData:imageData];
                
                @synchronized([MainSocketDelegate connectedSocketsQueue])
                {
                    MiniSocket *_sock = [self isBuddyOnline:userID];   // 判断自己是否在线
                    if (_sock != nil)
                    {
                        if([[[_sock miniAsynSocket] connectedHost] isEqual:[packet.subAsynSocket connectedHost]])
                        {
                            NSData *data =[[NSData alloc] init];
                            NSData *dataWithCmd = [self dataCmd:data cmd:CMD_FUN_LOG subcmd:CMD_LOG_REPEAT_LOGIN];
                            [packet.subAsynSocket writeData:dataWithCmd withTimeout:-1 tag:0];
                            return;

                        }
                        else 
                        {
                            NSData *data =[[NSData alloc] init];
                            NSData *dataWithCmd = [self dataCmd:data cmd:CMD_FUN_LOG subcmd:CMD_LOG_CHANGE_LOGIN];
                            [_sock.miniAsynSocket writeData:dataWithCmd withTimeout:-1 tag:0];
                            [_sock.miniAsynSocket disconnect];                            
                        }
                        
                    }
                }
                NSData *dataWithCmd = [self dataCmd:data cmd:CMD_FUN_LOG subcmd:CMD_LOG_RET_YES];
                [packet.subAsynSocket writeData:dataWithCmd withTimeout:-1 tag:0];
                
                // 查找该用户的所有好友，并向其发其所有在线好友发送上线提醒
                NSString *userIDStr = [self convertQQNumToString:userID];
                NSMutableString *sqlQueryForFriends = [[NSMutableString alloc] initWithFormat:@"SELECT * FROM tbFriends WHERE UserId = '"];
                [sqlQueryForFriends appendString:userIDStr];
                [sqlQueryForFriends appendString:@"'"];
                NSMutableArray *buddyList = [mysql doDataQuery:sqlQueryForFriends];
                for (NSInteger i=0; i<[buddyList count]; ++i)
                {
                    NSMutableArray *buddy = [buddyList objectAtIndex:i];
                    if ([buddy count] > COLUMN_OF_FRIENDID_IN_TBFRIENDS)   // 读出的数据有问题(比如数据表的字段修改了)
                    {
                        NSString *buddyIdStr = [buddy objectAtIndex:COLUMN_OF_FRIENDID_IN_TBFRIENDS];
                        NSInteger buddyId = [buddyIdStr intValue];
                        MiniSocket *_sock = [self isBuddyOnline:buddyId];   // 判断该好友是否在线
                        if (_sock != nil)
                        {
                            // 产生上线提醒包
                            NSString *ipStr = [_sock.miniAsynSocket connectedHost];
                            NSData *ipData = [NSKeyedArchiver archivedDataWithRootObject:ipStr];
                            NSData *reply = [self createStatusNotifyPakcet:OP_STATUS_NOTIFY_ONLINE error:ERR_NO_ERROR userId:userIDStr userIp:ipData];
                            NSInteger sendLength = [reply length];
                            NSMutableData *sendData = [[NSMutableData alloc] initWithBytes:&sendLength length:sizeof(sendLength)];
                            [sendData appendData:reply];
                            [_sock.miniAsynSocket writeData:sendData withTimeout:-1 tag:0];
                        }
                    }
                }
                

                @synchronized([MainSocketDelegate connectedSocketsQueue])
                {
                    for (MiniSocket *_sock in [MainSocketDelegate connectedSocketsQueue]) {
                        if ([_sock.miniAsynSocket.connectedHost isEqualTo:packet.subAsynSocket.connectedHost]
                            && (_sock.miniAsynSocket.connectedPort ==packet.subAsynSocket.connectedPort))
                        {
                            _sock.userId = userID;
                        }
                    }
                }

            }
            else
            {
                NSLog(@"Can not find userID&&pwd in the database");
                NSData *data = [[NSData alloc] init];
                NSData *dataWithCmd = [self dataCmd:data cmd:CMD_FUN_LOG subcmd:CMD_LOG_RET_NO];
                [packet.subAsynSocket writeData:dataWithCmd withTimeout:-1 tag:0];    
            }
        }
        break;
        default:
            NSLog(@"unknoew login request");            
            break;
    }
    //结束数据库连接  
    [mysql disconnect];

}

// 把 NSInteger 的qq号转换为 NSString 的
- (NSString *)convertQQNumToString:(NSInteger)qqNum
{
#ifndef QQ_NUM_LEN
#define QQ_NUM_LEN 10
#endif
    NSMutableString *qqNumStr = [[NSMutableString alloc] initWithFormat:@"%ld", qqNum];
    while ([qqNumStr length] != QQ_NUM_LEN)
    {
        [qqNumStr insertString:@"0" atIndex:0];
    }
    return qqNumStr;
}

// 产生 上、下线提醒包
- (NSData *)createStatusNotifyPakcet:(NSInteger)status error:(NSInteger)isError userId:(NSString *)userId userIp:(NSData *)userIp
{
    STATUSNOTIFYHRD *replyHRD;
    NSInteger packetLength = 0;
    if (isError != ERR_NO_ERROR)
    {
        packetLength = sizeof(STATUSNOTIFYHRD);
        replyHRD = (STATUSNOTIFYHRD *)NewPtr(packetLength);
        
        replyHRD->type = CMD_FUN_STATUSNOTIFY;
        replyHRD->operation = status;
        replyHRD->error = isError;
        replyHRD->userid_len = 0;
        replyHRD->userip_len = 0;
    }
    else
    {
        NSData *userIdData = [NSKeyedArchiver archivedDataWithRootObject:userId];
        
        packetLength = sizeof(STATUSNOTIFYHRD) + [userIdData length] + [userIp length];
        replyHRD = (STATUSNOTIFYHRD *)NewPtr(packetLength);
        
        replyHRD->type = CMD_FUN_STATUSNOTIFY;
        replyHRD->operation = status;
        replyHRD->error = isError;
        replyHRD->userid_len = [userIdData length];
        replyHRD->userip_len = [userIp length];
        
        char *replyUserId = (char *)replyHRD + sizeof(STATUSNOTIFYHRD);
        [userIdData getBytes:replyUserId length:[userIdData length]];
        
        char *replyUserIp = (char *)replyHRD + sizeof(STATUSNOTIFYHRD) + [userIdData length];
        [userIp getBytes:replyUserIp length:[userIp length]];
    }
    NSData *reply = [[NSData alloc] initWithBytes:replyHRD length:packetLength];
    DisposePtr((char *)replyHRD);
    return reply;
}

// 判断 userId 对应的用户是否在线
- (MiniSocket *)isBuddyOnline:(NSInteger)userId
{
    @synchronized([MainSocketDelegate connectedSocketsQueue])
    {
        // 遍历 connectedSocketQueue，找到该好友的 _sock
        for (MiniSocket *_sock in [MainSocketDelegate connectedSocketsQueue]) 
        {
            if (_sock.userId == userId)
            {
                return _sock;
            }
        }
        return nil;
    }
}

@end
